/*
 * @(#)XfmtOutputPanel.java        2003/01/01
 *
 * This file is part of Xfuzzy 3.0, a design environment for fuzzy logic
 * based systems.
 *
 * (c) 2000 IMSE-CNM. The authors may be contacted by the email address:
 *                    xfuzzy-team@imse.cnm.es
 *
 * Xfuzzy is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * Xfuzzy is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */


package xfuzzy.xfmt;

import xfuzzy.lang.*;
import xfuzzy.util.*;
import javax.swing.*;
import java.awt.*;

/**
 * Panel que representa una variable de salida
 * 
 * @author Francisco Jos� Moreno Velo
 *
 */
public class XfmtOutputPanel extends JPanel {
	
	//----------------------------------------------------------------------------//
	//                            CONSTANTES PRIVADAS                             //
	//----------------------------------------------------------------------------//

	/**
	 * C�digo asociado a la clase serializable
	 */
	private static final long serialVersionUID = 95505666603047L;
	
	//----------------------------------------------------------------------------//
	//                            MIEMBROS PRIVADOS                              //
	//----------------------------------------------------------------------------//
	
	/**
	 * Configuraci�n gr�fica para representar los ejes
	 */
	private Graphics2D gaxis;
	
	/**
	 * Configuraci�n gr�fica para representar las funciones de pertenencia
	 */
	private Graphics2D gmf;

	/**
	 * Configuraci�n gr�fica para representar la funci�n de pertenencia seleccionada
	 */
	private Graphics2D gsel;

	/**
	 * �rea donde situar la representaci�n
	 */
	private int x0, x1, y0, y1;
	
	/**
	 * M�nimo del universo de discurso de la partici�n difusa
	 */
	private double min;
	
	/**
	 * M�ximo del universo de discurso de la partici�n difusa
	 */
	private double max;
	
	/**
	 * Funci�n difusa asociada a la variable
	 */
	private MemFunc mf;
	
	/**
	 * Valor concretado de la variable
	 */
	private double value;
	
	/**
	 * Marcador para indicar que la variable se ha concretado
	 */
	private boolean valued;
	
	//----------------------------------------------------------------------------//
	//                                CONSTRUCTOR                                 //
	//----------------------------------------------------------------------------//

	/**
	 * Constructor
	 */
	public XfmtOutputPanel(int width,int height,Variable output) {
		super();
		Dimension prefsize = new Dimension(width,height);
		setPreferredSize(prefsize);
		setBackground(XConstants.textbackground);
		setBorder(BorderFactory.createLoweredBevelBorder());
		this.min = output.getType().getUniverse().min();
		this.max = output.getType().getUniverse().max();
	}
	
	//----------------------------------------------------------------------------//
	//                             M�TODOS P�BLICOS                               //
	//----------------------------------------------------------------------------//
	
	/**
	 * Asigna la funci�n y el valor concreto a representar
	 */	
	public void setFunction(MemFunc mf, double value) {
		this.mf = mf;
		this.value = value;
		this.valued = true;
	}
	
	/**
	 * Asigna la funci�n a representar
	 */
	public void setFunction(MemFunc mf) {
		this.mf = mf;
		this.valued = false;
	}
	
	/**
	 * Dibuja la representaci�n
	 */
	public void paint(Graphics g) {
		super.paint(g);
		setGraphics(g);
		paintAxis();
		paintFunction();
		if(valued) paintValue();
	}
	
	//----------------------------------------------------------------------------//
	//                             M�TODOS PRIVADOS                               //
	//----------------------------------------------------------------------------//
	
	/**
	 * Calcula algunas constantes necesarias
	 */
	private void setGraphics(Graphics gc) {
		gaxis = (Graphics2D) gc.create(); gaxis.setColor(Color.black);
		gmf = (Graphics2D) gc.create(); gmf.setColor(Color.blue);
		gsel = (Graphics2D) gc.create(); gsel.setColor(Color.red);
		Dimension size = getSize();
		x0 = size.width/8;
		x1 = size.width*7/8;
		y0 = size.height*7/8;
		y1 = size.height/8;
	}
	
	/**
	 * Dibuja el valor concreto en la representaci�n
	 */
	private void paintValue() {
		int pos = x0 + (int) ((value-min)*(x1-x0)/(max-min));
		gsel.drawLine(pos, y0, pos, y1);
	}
	
	/**
	 * Dibuja la funci�n de pertenencia en la representaci�n
	 */
	private void paintFunction() {
		if(mf == null) return;
		if(mf instanceof xfuzzy.pkg.xfl.mfunc.singleton) {
			double val = ((ParamMemFunc) mf).get()[0];
			int pos = x0 + (int) ((val-min)*(x1-x0)/(max-min));
			gmf.drawLine(pos, y0, pos, y1);
			return;
		}
		if((mf instanceof AggregateMemFunc) &&
				((AggregateMemFunc) mf).isDiscrete() ) {
			double[][] val = ((AggregateMemFunc) mf).getDiscreteValues();
			for(int i=0; i<val.length; i++){
				int xpos = x0 + (int) ((val[i][0]-min)*(x1-x0)/(max-min));
				int ypos = y0 + (int) (val[i][1]*(y1-y0));
				gmf.drawLine(xpos, y0, xpos, ypos);
			}
			return;
		}
		double yval = mf.compute(0);
		int ypos = y0 + (int) (yval*(y1-y0));
		for(int i=1; i<(x1-x0); i++) {
			double nval = mf.compute( min + (max-min)*i/(x1-x0) );
			int npos = y0 + (int) (nval*(y1-y0));
			gmf.drawLine(x0+i, ypos, x0+i+1, npos);
			ypos = npos;
		} 
	}
	
	/**
	 * Dibuja los ejes de la representaci�n
	 */
	private void paintAxis() {
		gaxis.drawLine(x0-1, y0+1, x0-1, y1);
		gaxis.drawLine(x0-1, y0+1, x1+1, y0+1);
		gaxis.drawLine(x1+1, y0+1, x1+1, y1);
	}
}
